/****************************************************************************/
/***                                                                      ***/
/***   (C) 2012-2014 Dierk Ohlerich et al., all rights reserved.          ***/
/***                                                                      ***/
/***   Released under BSD 2 clause license, see LICENSE.TXT               ***/
/***                                                                      ***/
/****************************************************************************/

mtrl sFixedShaderFlat
{
    permute PCol;
    permute PTex { Off,On,AlphaOnly,Monochrome,RedAlpha };
    permute PW;

    struct ia2vs
    {
        pif(PW)
            float4 posw : POSITION;
        pelse
            float3 pos : POSITION;
        pif(PCol)
            min10float4 color : COLOR;
        pif(PTex)
            min16float2 uv0 : TEXCOORD0;
    };

    struct vs2ps
    {
        pif(PCol)
            min10float4 color : COLOR;
        pif(PTex)
            min16float2 uv0 : TEXCOORD0;
    }; 

    cbuffer cbvs : vs(0) : register(0)
    {
        row_major float4x4 MS2SS;
    };

    // hlsl3

    vs hlsl3
    {
        void main(in ia2vs i,out vs2ps o,out float4 tpos:POSITION)
        {
            pif(PW)
                tpos = mul(MS2SS,i.posw); 
            pelse
                tpos = mul(MS2SS,float4(i.pos,1));
            pif(PCol)
                o.color = i.color;
            pif(PTex)
                o.uv0 = i.uv0;
        }
    };

    ps hlsl3
    {
        pif(PTex)
        {
            SamplerState sam0 : register(s0);
        }
        void main(in vs2ps i,out float4 r:COLOR)
        {
            pif(PCol)
                r = i.color;    
            pelse
                r = 1;
            pif(PTex==PTex.On)
                r *= tex2D(sam0,i.uv0);
            pif(PTex==PTex.AlphaOnly)
                r.w *= tex2D(sam0,i.uv0).w;
            pif(PTex==PTex.Monochrome)
                r.xyz *= tex2D(sam0,i.uv0).r;
            pif(PTex==PTex.RedAlpha)
                r *= tex2D(sam0,i.uv0).r;
        }
    };


    // hlsl5

    vs hlsl5
    {
        void main(in ia2vs i,out vs2ps o,out float4 tpos:SV_Position)
        {
            pif(PW)
                tpos = mul(MS2SS,i.posw); 
            pelse
                tpos = mul(MS2SS,float4(i.pos,1));
            pif(PCol)
                o.color = i.color;
            pif(PTex)
                o.uv0 = i.uv0;
        }
    };

    ps hlsl5
    {
        pif(PTex)
        {
            SamplerState sam0 : register(s0);
            Texture2D tex0 : register(t0);
        }
        void main(in vs2ps i,out float4 r:SV_Target)
        {
            pif(PCol)
                r = i.color;    
            pelse
                r = 1;
            pif(PTex==PTex.On)
                r *= tex0.Sample(sam0,i.uv0);
            pif(PTex==PTex.AlphaOnly)
                r.w *= tex0.Sample(sam0,i.uv0).w;
            pif(PTex==PTex.Monochrome)
                r.xyz *= tex0.Sample(sam0,i.uv0).r;
            pif(PTex==PTex.RedAlpha)
                r *= tex0.Sample(sam0,i.uv0).r;
        }
    };

    // glsl1

    vs glsl1
    {
        void main()
        {
            pif(PW)
                gl_Position = MS2SS*i_posw; 
            pelse
                gl_Position = MS2SS*vec4(i_pos,1);
            pif(PCol)
                o_color = i_color;
            pif(PTex)
                o_uv0 = i_uv0;
        }
    };

    ps glsl1
    {
        pif(PTex)
        {
            uniform sampler2D sam0;
        }

        void main()
        {
            pif(PCol)
                lowp vec4 col = i_color;    
            pelse
                lowp vec4 col = vec4(1.0,1.0,1.0,1.0);
            pif(PTex==PTex.On)
                col *= texture2D(sam0,i_uv0);
            pif(PTex==PTex.AlphaOnly)
                col.w *= texture2D(sam0,i_uv0).w;
            pif(PTex==PTex.Monochrome)
                col.xyz *= texture2D(sam0,i_uv0).r;
            pif(PTex==PTex.RedAlpha)
                col *= texture2D(sam0,i_uv0).r;
            gl_FragColor = col;
        }
    };
}

/****************************************************************************/

mtrl sFixedShaderLight
{
    permute PCol;
    permute PTex { Off,On,AlphaOnly };

    struct ia2vs
    {
        float3 pos : POSITION;
        min16float3 normal : NORMAL;
        pif(PCol)
            min10float4 vcolor : COLOR;
        pif(PTex)
            min16float2 uv0 : TEXCOORD0;
    };

    struct vs2ps
    {
        min10float4 color : COLOR;
        pif(PTex)
            min16float2 uv0 : TEXCOORD0;
    };


    cbuffer cbvs : vs(0) : register(0)
    {
        row_major float4x4 MS2SS;
        float4 LightDirX;
        float4 LightDirY;
        float4 LightDirZ;
        float4 LightColR;
        float4 LightColG;
        float4 LightColB;
        float3 Ambient;
    };

    // hlsl3

    vs hlsl3
    {
        void main(in ia2vs i,out vs2ps o,out float4 tpos:POSITION)
        {
            tpos = mul(MS2SS,float4(i.pos,1));

            float4 l;           
            l = LightDirX*i.normal.xxxx
                + LightDirY*i.normal.yyyy
                + LightDirZ*i.normal.zzzz;
            l = max(l,0);

            o.color.x = dot(LightColR,l);
            o.color.y = dot(LightColG,l);
            o.color.z = dot(LightColB,l);
            o.color.w = 1.0;

            pif(PCol)
                o.color *= i.vcolor;
            o.color.xyz += Ambient;

            pif(PTex)
                o.uv0 = i.uv0;
        }
    };

    ps hlsl3
    {
        pif(PTex)
            SamplerState sam0 : register(s0);

        void main(in vs2ps i,out float4 r:COLOR)
        {
            r = i.color;
            pif(PTex==PTex.On)
                r *= tex2D(sam0,i.uv0);
            pif(PTex==PTex.AlphaOnly)
                r.w *= tex2D(sam0,i.uv0).w;
        }
    };

    // hlsl5

    vs hlsl5
    {
        void main(in ia2vs i,out vs2ps o,out float4 tpos:SV_Position)
        {
            tpos = mul(MS2SS,float4(i.pos,1));

            float4 l;           
            l = LightDirX*i.normal.xxxx
                + LightDirY*i.normal.yyyy
                + LightDirZ*i.normal.zzzz;
            l = max(l,0);

            o.color.x = dot(LightColR,l);
            o.color.y = dot(LightColG,l);
            o.color.z = dot(LightColB,l);
            o.color.w = 1.0;

            pif(PCol)
                o.color *= i.vcolor;
            o.color.xyz += Ambient;

            pif(PTex)
                o.uv0 = i.uv0;
        }
    };

    ps hlsl5
    {
        pif(PTex)
        {
            SamplerState sam0 : register(s0);
            Texture2D tex0 : register(t0);
        }

        void main(in vs2ps i,out float4 r:SV_Target)
        {
            r = i.color;
            pif(PTex==PTex.On)
                r *= tex0.Sample(sam0,i.uv0);
            pif(PTex==PTex.AlphaOnly)
                r.w *= tex0.Sample(sam0,i.uv0).w;
        }
    };  

    // glsl1

    vs glsl1
    {
        void main()
        {
            gl_Position = MS2SS*vec4(i_pos,1);

            lowp vec4 l;
            l = LightDirX*i_normal.xxxx
                + LightDirY*i_normal.yyyy
                + LightDirZ*i_normal.zzzz;
            l = max(l,vec4(0,0,0,0));

            o_color.x = dot(LightColR,l);
            o_color.y = dot(LightColG,l);
            o_color.z = dot(LightColB,l);
            o_color.w = 1.0;

            pif(PCol)
                o_color *= i_vcolor;
            o_color.xyz += Ambient;

            pif(PTex)
                o_uv0 = i_uv0;
        }
    };

    ps glsl1
    {
        pif(PTex)
            uniform sampler2D tex0;

        void main()
        {
            pif(PTex==PTex.On)
                gl_FragColor = i_color * texture2D(tex0,i_uv0);
            pif(PTex==PTex.AlphaOnly)
            {
                i_color.w *= texture2D(tex0,i_uv0).w;
                gl_FragColor.w = i_color;
            }
            pif(PTex==PTex.Off)
                gl_FragColor = i_color;
        }
    };  
}

/****************************************************************************/
/***                                                                      ***/
/***   Shaders for DrawXXXIndirect                                        ***/
/***                                                                      ***/
/****************************************************************************/

// Parameters : 

//

// para0.x : Index
// para0.y : IndexCountPerInstance / VertexCountPerInstance
// para0.z : InstanceCount
// para0.w : StartIndexLocation / StartVertexLocation

// para1.x : StartInstanceLocation
// para1.y : BaseVertexLocation
// para1.z : pad0
// para1.w : pad1


mtrl DrawIndexedInstancedIndirectShader
{
    cbuffer cbc0 : cs(0) : register(0)
    {
        uint4 counts;
        uint4 para0;
        uint4 para1;
    };

    cs hlsl5
    {
        RWBuffer<uint> output : register(u0);

        [numthreads(1,1,1)]
        void main(uint3 tid:SV_DispatchThreadID)
        {
            int count = para0.z;

            count *= counts.x;
            count *= counts.y;
            count *= counts.z;
            count *= counts.w;
            count += para1.z;

            uint Index = para0.x;
            output[Index+0] = para0.y;
            output[Index+1] = count;
            output[Index+2] = para0.w;
            output[Index+3] = para1.y;
            output[Index+4] = para1.x;
        }
    };
} 

mtrl DrawInstancedIndirectShader
{
    cbuffer cbc0 : cs(0) : register(0)
    {
        uint4 counts;
        uint4 para0;
        uint4 para1;
    };

    cs hlsl5
    {
        RWBuffer<uint> output : register(u0);

        [numthreads(1,1,1)]
        void main(uint3 tid:SV_DispatchThreadID)
        {
            int count = para0.z;

            count *= counts.x;
            count *= counts.y;
            count *= counts.z;
            count *= counts.w;
            count += para1.z;

            uint Index = para0.x;
            output[Index+0] = para0.y;
            output[Index+1] = count;
            output[Index+2] = para0.w;
            output[Index+3] = para1.x;
        }
    };
}

mtrl DispatchIndirectShader
{
    cbuffer cbc0 : cs(0) : register(0)
    {
        uint4 counts;
        uint4 para0;
        uint4 para1;
    };

    cs hlsl5
    {
        RWBuffer<uint> output : register(u0);

        [numthreads(1,1,1)]
        void main(uint3 tid:SV_DispatchThreadID)
        {
            int count = para0.z;

            count *= counts.x;
            count *= counts.y;
            count *= counts.z;
            count *= counts.w;
            count += para1.z;

            uint Index = para0.x;
            output[Index+0] = (count+para1.z-1)/para1.z;
            output[Index+1] = 1;
            output[Index+2] = 1;
        }
    };
} 

/****************************************************************************/

mtrl sComputeSyncShader
{
    struct ia2vs
    {
       float3 pos : POSITION;
    };

    struct vs2ps
    {
    }; 

    // hlsl5

    vs hlsl5
    {
        void main(in ia2vs i,out vs2ps o,out float4 tpos:SV_Position)
        {
            tpos = float4(i.pos,1);
        }
    };

    ps hlsl5
    {
        RWBuffer<uint> output : register(u1);

        void main(in vs2ps i,out float4 r:SV_Target)
        {
            output[0] = output[0] + 1;
            r = output[0]*0.04;
        }
    };
}

/****************************************************************************/
